/*************************************************************************
 *
 *  Copyright (C) 2013 Florian Dang <florian.coin@gmail.com>
 *
 *  This file is part of NatusVerse.
 *
 *  NatusVerse is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  NatusVerse is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with NatusVerse.  If not, see <http://www.gnu.org/licenses/>.
 *
 *************************************************************************/


#ifndef INC_UTILS_H_
#define INC_UTILS_H_

#include <sys/types.h>
#include <unistd.h>
#include <stdint.h> // to specify exact-width t_integer types

#include <iostream>
#include <cstdlib>
#include <cmath>
#include <ctime>

// A macro to disallow the copy constructor and operator= functions
// This should be used in the private: declarations for a class
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
  TypeName(const TypeName&);               \
  void operator=(const TypeName&)

static const int default_width  = 1024;
static const int default_height = 768;

/*! \var	typedef int32_t	t_int
 *	\brief	Integer
 */
typedef int32_t     t_int;

/*! \var	typedef uint32_t	t_uint
 *	\brief	Unsigned integer
 */
typedef uint32_t	t_uint;

/*! \var	typedef double		t_float;
 *	\brief	Float or double
 */
typedef double      t_float;


#define MASTER_NODE 0

typedef enum
{
	TAG_STEP,
	TAG_GRID,
	TAG_END
} t_tag_mpi;

static const char usage[] = "\
Usage :\n\
Look README for the moment\n\
";	/*!< Usage */


// invsqrt test
// static float InvSqrt(float x)
// {
// 	float xhalf=.5f*x;
// 	int i=*(int*)&x;
// 	i=0x5f3759df-(i>>1);
// 	x=*(float*)&i;
// 	x=x*(1.5f-xhalf*x*x);
// 	return x;
// }

template <class T>
class Utils
{
	public:
		inline static const T& max(const T& a, const T& b);
		inline static const T& min(const T& a, const T& b);

		static void   DispMat(const int n, T *m, std::string str);
		static void   DispVect(const int n, T *m, std::string str);
		static void   DispVect(const int n, T *m, int begin, int end, std::string str);
};

class Rand
{
	public:
		static float RFloat()
		{
			// [0;1[
			static int init_alea = 1;
			if (init_alea)
				srand(getpid());

			init_alea = 0;

			return (float) rand() / (float) RAND_MAX;
		}

		static int   RInt(int begin, int range)
		{
			//[begin..begin+range[
			return begin + (int)(range * RFloat());
		}
};



template <class T>
inline const T& Utils<T>::max(const T& a, const T& b)
{
	return (b < a) ? a : b;
}

template <class T>
inline const T& Utils<T>::min(const T& a, const T& b)
{
	return (b > a) ? a : b;
}

template <class T>
void Utils<T>::DispMat(const int n, T *m, std::string str)
{
	std::cout << str << std::endl;
	for (int i = 0; i < n; i ++)
	{
		for (int j = 0; j < n; j ++)
			std::cout << m[i * n + j] << " ";
		std::cout << std::endl;
	}
}

template <class T>
void Utils<T>::DispVect(const int n, T *v, std::string str)
{
	std::cout << str << std::endl;
	for (int j = 0; j < n; j ++)
		std::cout << v[j] << " ";
	std::cout << std::endl;
}

template <class T>
void Utils<T>::DispVect(const int n, T *v, int begin, int end, std::string str)
{
	std::cout << str << std::endl;
	for (int j = begin; j < end; j ++)
		std::cout << v[j] << " ";
	std::cout << std::endl;
}

#endif  // INC_UTILS_H_

